<?php


/**
 * 手动抛出异常，用于中断程序
 *
 * @param string $msg 返回信息
 * @return void
 */
function throwBusinessException($msg)
{
    throw new \App\Exceptions\BusinessException($msg);
}

function code62($x)
{
    $show = '';
    while ($x > 0) {
        $s = $x % 62;
        if ($s > 35) {
            $s = chr($s + 61);
        } elseif ($s > 9 && $s <= 35) {
            $s = chr($s + 55);
        }
        $show .= $s;
        $x = floor($x / 62);
    }
    return $show;
}

function shorturl($url, $domain)
{
    // crc32() 函数计算字符串的 32 位 CRC（循环冗余校验） http://www.w3school.com.cn/php/func_string_crc32.asp
    $url = crc32($url);
    $result = sprintf("%u", $url);
    return ['url' => $domain . 's/' . code62($result), 'code' => code62($result)];
}

/**
 * 获取指定日期段内每一天的日期
 *
 * @param Date $startdate 开始日期
 * @param Date $enddate 结束日期
 * @return Array
 */
function getDateFromRange($startdate, $enddate)
{
    $stimestamp = strtotime($startdate);
    $etimestamp = strtotime($enddate);

    // 计算日期段内有多少天
    $days = ($etimestamp - $stimestamp) / 86400 + 1;
    // 保存每天日期
    $date = array();

    for ($i = 0; $i < $days; $i++) {
        $date [] = date('Y-m-d', $stimestamp + (86400 * $i));
    }
    //arsort($date);
    return $date;
}


/** 商品sku
 * @param $goods
 * @return array|mixed
 */
function cartesianProduct($goods)
{
    if (count($goods) == 1) {
        return $returnData[] = $goods[0];
    }
    $returnData = [];

    for ($i = 0; $i < count($goods) - 1; $i++) {

        // 初始化
        if ($i == 0) {
            $returnData = $goods[$i];
        }

        $tempArray = []; // 临时数组

        foreach ($returnData as $val) {
            foreach ($goods[$i + 1] as $v) {
                $tempArray[] = $val . ',' . $v;
            }
        }
        //重新赋值
        $returnData = $tempArray;
    }
    return $returnData;
}

/**
 * 调试变量信息,终止执行
 * @param $arr
 * @return void
 * @author jroam
 */
function myDie($arr)
{
    echo "<pre>";
    print_r($arr);
    die("</pre>");
}

/**
 * 调试变量信息,继续执行
 * @param $arr
 * @return void
 * @author jroam
 */
function myPrint($arr)
{
    echo "<pre>";
    print_r($arr);

    echo("</pre>");
}


/**
 * 接品返回数据格式
 * @param int $status 状态码
 * @param string $msg
 * @param array $data
 * @return \Illuminate\Http\JsonResponse
 * @author jroam
 */
function result($status, $msg, $data = [])
{
    return response()->json([
        "status" => $status,
        "msg" => $msg,
        "data" => $data
    ]);
}

/**
 * 成功
 *
 * @param string $msg
 * @param array $data
 * @return \Illuminate\Http\JsonResponse
 */
function success($msg = '', $data = [])
{
    return result(\App\Http\Common\InterfaceStatusCode::SUCCESS, $msg, $data);
}

/**
 * 失败
 *
 * @param string $msg
 * @param array $data
 * @return \Illuminate\Http\JsonResponse
 */
function error($msg = '', $data = [])
{
    return result(\App\Http\Common\InterfaceStatusCode::CHECK_FAIL, $msg, $data);
}

/**
 * 检测身份证号码
 *
 * @param string $id 身份证号码
 * @return bool
 */
function checkIdCard($id)
{
    $id = strtoupper($id);
    $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
    $arr_split = [];
    if (!preg_match($regx, $id)) {
        return false;
    }
    if (15 == strlen($id)) {
        //检查15位
        $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";

        @preg_match($regx, $id, $arr_split);
        //检查生日日期是否正确
        $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
        if (!strtotime($dtm_birth)) {
            return false;
        } else {
            return true;
        }
    } else {
        //检查18位
        $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
        @preg_match($regx, $id, $arr_split);
        $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
        //检查生日日期是否正确
        if (!strtotime($dtm_birth)) {
            return false;
        } else {
            //检验18位身份证的校验码是否正确。
            //校验位按照ISO 7064:1983.MOD 11-2的规定生成，X可以认为是数字10。
            $arr_int = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
            $arr_ch = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
            $sign = 0;
            for ($i = 0; $i < 17; $i++) {
                $b = (int)$id[$i];
                $w = $arr_int[$i];
                $sign += $b * $w;
            }
            $n = $sign % 11;
            $val_num = $arr_ch[$n];
            if ($val_num != substr($id, 17, 1)) {
                return false;
            } else {
                return true;
            }
        }
    }

}

/**
 *验证是否是手机号
 * @param $phone 手机号
 * @return false|int
 * @author jroam
 */
function checkPhone($phone)
{
    return preg_match(config('cdd.public.rePhone'), $phone);
}


/**
 * 生成随机码
 *
 * @param int $length
 * @param string $codeSet
 * @return string
 */
function generateRandomCode($length = 6, $codeSet = "a0bc1de2fg3hi4jk56lmnopqrstuv8wxy9z7")
{
    $code = "";
    for ($i = 0; $i < $length; $i++) {
        $code .= $codeSet [mt_rand(0, strlen($codeSet) - 1)];
    }
    return $code;
}


/**
 * 只保留字符串首尾字符，隐藏中间用*代替（两个字符时只显示第一个）
 * @param string $user_name 姓名
 * @return string 格式化后的姓名
 */
function substr_cut($user_name)
{
    $strlen = mb_strlen($user_name, 'utf-8');
    $firstStr = mb_substr($user_name, 0, 1, 'utf-8');
    $lastStr = mb_substr($user_name, -1, 1, 'utf-8');
    return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($user_name, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr;
}


/**
 * 方法 isDate
 *
 * @author jq
 * 功能 判断日期格式是否正确
 * 参数 $str 日期字符串
 * $format 日期格式
 * 返回 无
 */
function is_Date($str, $format = 'Y-m-d')
{
    $unixTime_1 = strtotime($str);
    if (!is_numeric($unixTime_1)) return false; //如果不是数字格式，则直接返回
    $checkDate = date($format, $unixTime_1);
    $unixTime_2 = strtotime($checkDate);
    if ($unixTime_1 == $unixTime_2) {
        return true;
    } else {
        return false;
    }
}

/**
 * 返回 成功JSON 响应
 *
 * @param int $code 状态码
 * @param string $msg 消息
 * @param mixed $data 数据
 * @return \Illuminate\Http\JsonResponse
 */
function successResponse($msg, $data = null)
{
    return response()->json([
        "code" => \App\Http\Common\InterfaceStatusCode::SUCCESS,
        "msg" => $msg,
        "data" => $data
    ]);
}

/**
 * 返回 成功JSON 响应
 *
 * @param int $code 状态码
 * @param string $msg 消息
 * @param mixed $data 数据
 * @return \Illuminate\Http\JsonResponse
 */
function errorResponse($msg, $data = null)
{
    return response()->json([
        "code" => \App\Http\Common\InterfaceStatusCode::ERROR,
        "msg" => $msg,
        "data" => $data
    ]);
}

/**
 * 执行 CURL GET 请求并返回 JSON 数据
 *
 * @param string $url 请求 URL
 * @param array $data GET 参数
 * @param int $timeout 超时时间 (秒)
 * @return mixed 解码后的 JSON 数据或 false
 */
function curlGetJson($url, $data = [], $timeout = 30)
{
    if (!empty($data)) {
        $url .= '?' . http_build_query($data);
    }

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    // 如果是 HTTPS，可能需要以下选项
    // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);

    curl_close($ch);

    if ($response === false) {
        // 处理 CURL 错误
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    // 检查 HTTP 状态码，例如 200 OK
    if ($httpCode !== 200) {
        // 处理非 200 状态码
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    $jsonData = json_decode($response, true);

    // 检查 JSON 解码错误
    if (json_last_error() !== JSON_ERROR_NONE) {
        // 处理 JSON 解码错误
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    return $jsonData;
}

/**
 * 执行 CURL POST 请求并返回 JSON 数据
 *
 * @param string $url 请求 URL
 * @param array $data POST 数据
 * @param int $timeout 超时时间 (秒)
 * @return mixed 解码后的 JSON 数据或 false
 */
function curlPostJson($url, $data = [], $timeout = 30)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 对于数组，curl 会自动设置 Content-Type 为 multipart/form-data 或 application/x-www-form-urlencoded
    // 如果需要发送 JSON 数据，可以设置 Content-Type 并将数据编码为 JSON 字符串
    // curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    // curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));

    // 如果是 HTTPS，可能需要以下选项
    // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    // curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);

    curl_close($ch);

    if ($response === false) {
        // 处理 CURL 错误
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    // 检查 HTTP 状态码，例如 200 OK
    if ($httpCode !== 200) {
        // 处理非 200 状态码
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    $jsonData = json_decode($response, true);

    // 检查 JSON 解码错误
    if (json_last_error() !== JSON_ERROR_NONE) {
        // 处理 JSON 解码错误
        // 可以根据需要记录错误或返回特定的错误结构
        return false; // 或者返回一个包含错误信息的数组/对象
    }

    return $jsonData;
}
